`define DATA_WIDTH 32
`define BYTE_WIDTH 8

`define INSTRUCTION_BYTES 4
`define INSTRUCTION_OP_WIDTH 6
`define INSTRUCTION_OP_BEGIN 31
`define INSTRUCTION_OP_END 26
`define REGISTER_ADDRESS_WIDTH 5
`define INSTRUCTION_RS_BEGIN 25
`define INSTRUCTION_RS_END 21
`define INSTRUCTION_RT_BEGIN 20
`define INSTRUCTION_RT_END 16
`define INSTRUCTION_RD_BEGIN 15
`define INSTRUCTION_RD_END 11
`define INSTRUCTION_SA_WIDTH 5
`define INSTRUCTION_SA_BEGIN 10
`define INSTRUCTION_SA_END 6
`define INSTRUCTION_SA_EXT_WIDTH 27
`define INSTRUCTION_FUNC_WIDTH 6
`define INSTRUCTION_FUNC_BEGIN 5
`define INSTRUCTION_FUNC_END 0
`define INSTRUCTION_IMM_WIDTH 16
`define INSTRUCTION_IMM_BEGIN 15
`define INSTRUCTION_IMM_END 0
`define INSTRUCTION_IMM_EXT_WIDTH 16
`define INSTRUCTION_J_ADDR_WIDTH 26
`define INSTRUCTION_J_ADDR_BEGIN 25
`define INSTRUCTION_J_ADDR_END 0
`define INSTRUCTION_J_ADDR_EXT_WIDTH 6
`define INSTRUCTION_J_ADDR_PC_EXT_BEGIN 31
`define INSTRUCTION_J_ADDR_PC_EXT_END 28

`define INSTRUCTION_NOP 32'b00000000000000000000000000000000
`define INSTRUCTION_OP_SPECIAL 6'b000000
`define INSTRUCTION_OP_ADDIU 6'b001001
`define INSTRUCTION_FUNC_ADDU 6'b100001
`define INSTRUCTION_FUNC_SLT 6'b101010
`define INSTRUCTION_OP_SLTI 6'b001010
`define INSTRUCTION_OP_SLTIU 6'b001011
`define INSTRUCTION_FUNC_SLTU 6'b101011
`define INSTRUCTION_FUNC_SUBU 6'b100011
`define INSTRUCTION_FUNC_MULT 6'b011000
`define INSTRUCTION_FUNC_MFLO 6'b010010
`define INSTRUCTION_FUNC_MFHI 6'b010000
`define INSTRUCTION_FUNC_MTLO 6'b010011
`define INSTRUCTION_FUNC_MTHI 6'b010001
`define INSTRUCTION_OP_BEQ 6'b000100
`define INSTRUCTION_OP_REGIMM 6'b000001
`define INSTRUCTION_RT_BGEZ 5'b00001
`define INSTRUCTION_RT_BGEZAL 5'b10001
`define INSTRUCTION_RT_BLTZ 5'b00000
`define INSTRUCTION_RT_BLTZAL 5'b10000
`define INSTRUCTION_OP_BGTZ 6'b000111
`define INSTRUCTION_OP_BLEZ 6'b000110
`define INSTRUCTION_OP_BNE 6'b000101
`define INSTRUCTION_OP_J 6'b000010
`define INSTRUCTION_OP_JAL 6'b000011
`define INSTRUCTION_FUNC_JALR 6'b001001
`define INSTRUCTION_FUNC_JR 6'b001000
`define INSTRUCTION_OP_LW 6'b100011
`define INSTRUCTION_OP_SW 6'b101011
`define INSTRUCTION_OP_LB 6'b100000
`define INSTRUCTION_OP_LBU 6'b100100
`define INSTRUCTION_OP_SB 6'b101000
`define INSTRUCTION_FUNC_AND 6'b100100
`define INSTRUCTION_OP_ANDI 6'b001100
`define INSTRUCTION_OP_LUI 6'b001111
`define INSTRUCTION_FUNC_NOR 6'b100111
`define INSTRUCTION_FUNC_OR 6'b100101
`define INSTRUCTION_OP_ORI 6'b001101
`define INSTRUCTION_FUNC_XOR 6'b100110
`define INSTRUCTION_OP_XORI 6'b001110
`define INSTRUCTION_FUNC_SLL 6'b000000
`define INSTRUCTION_FUNC_SLLV 6'b000100
`define INSTRUCTION_FUNC_SRA 6'b000011
`define INSTRUCTION_FUNC_SRAV 6'b000111
`define INSTRUCTION_FUNC_SRL 6'b000010
`define INSTRUCTION_FUNC_SRLV 6'b000110
`define INSTRUCTION_FUNC_SYSCALL 6'b001100
`define INSTRUCTION_OP_CACHE 6'b101111
`define INSTRUCTION_OP_CP0 6'b010000
`define INSTRUCTION_FUNC_ERET 6'b011000
`define INSTRUCTION_FUNC_MFC0_MTC0 6'b000000
`define INSTRUCTION_RS_MFC0 5'b00000
`define INSTRUCTION_RS_MTC0 5'b00100
`define INSTRUCTION_FUNC_TLBWI 6'b000010
`define INSTRUCTION_OP_LHU 6'b100101

`define OPERATION_TYPE_WIDTH 3
`define OPERATION_TYPE_NOP 3'b000
`define OPERATION_TYPE_ALU 3'b001
`define OPERATION_TYPE_BRANCH 3'b010
`define OPERATION_TYPE_JUMP 3'b011

`define OPERATION_SUBTYPE_WIDTH 6
`define OPERATION_SUBTYPE_NOP 6'b000000
`define OPERATION_SUBTYPE_GET 6'b000001
`define OPERATION_SUBTYPE_EQUAL 6'b000010
`define OPERATION_SUBTYPE_NOT_EQUAL 6'b000011
`define OPERATION_SUBTYPE_LESS 6'b000100
`define OPERATION_SUBTYPE_LESS_UNSIGNED 6'b000101
`define OPERATION_SUBTYPE_LESS_EQUAL 6'b000110
`define OPERATION_SUBTYPE_GREATER 6'b000111
`define OPERATION_SUBTYPE_GREATER_EQUAL 6'b001000
`define OPERATION_SUBTYPE_AND 6'b001001
`define OPERATION_SUBTYPE_OR 6'b001010
`define OPERATION_SUBTYPE_XOR 6'b001011
`define OPERATION_SUBTYPE_NOR 6'b001100
`define OPERATION_SUBTYPE_ADD 6'b001101
`define OPERATION_SUBTYPE_SUB 6'b001110
`define OPERATION_SUBTYPE_SLL 6'b001111
`define OPERATION_SUBTYPE_SRA 6'b010000
`define OPERATION_SUBTYPE_SRL 6'b010001

`define MIPS_CPU_REGISTER_COUNT 32
`define MIPS_CPU_REGISTER_ZERO_NO 5'b00000
`define MIPS_CPU_REGISTER_AT_NO 5'b00001
`define MIPS_CPU_REGISTER_V0_NO 5'b00010
`define MIPS_CPU_REGISTER_V1_NO 5'b00011
`define MIPS_CPU_REGISTER_A0_NO 5'b00100
`define MIPS_CPU_REGISTER_A1_NO 5'b00101
`define MIPS_CPU_REGISTER_A2_NO 5'b00110
`define MIPS_CPU_REGISTER_A3_NO 5'b00111
`define MIPS_CPU_REGISTER_T0_NO 5'b01000
`define MIPS_CPU_REGISTER_T1_NO 5'b01001
`define MIPS_CPU_REGISTER_T2_NO 5'b01010
`define MIPS_CPU_REGISTER_T3_NO 5'b01011
`define MIPS_CPU_REGISTER_T4_NO 5'b01100
`define MIPS_CPU_REGISTER_T5_NO 5'b01101
`define MIPS_CPU_REGISTER_T6_NO 5'b01110
`define MIPS_CPU_REGISTER_T7_NO 5'b01111
`define MIPS_CPU_REGISTER_S0_NO 5'b10000
`define MIPS_CPU_REGISTER_S1_NO 5'b10001
`define MIPS_CPU_REGISTER_S2_NO 5'b10010
`define MIPS_CPU_REGISTER_S3_NO 5'b10011
`define MIPS_CPU_REGISTER_S4_NO 5'b10100
`define MIPS_CPU_REGISTER_S5_NO 5'b10101
`define MIPS_CPU_REGISTER_S6_NO 5'b10110
`define MIPS_CPU_REGISTER_S7_NO 5'b10111
`define MIPS_CPU_REGISTER_T8_NO 5'b11000
`define MIPS_CPU_REGISTER_T9_NO 5'b11001
`define MIPS_CPU_REGISTER_K0_NO 5'b11010
`define MIPS_CPU_REGISTER_K1_NO 5'b11011
`define MIPS_CPU_REGISTER_GP_NO 5'b11100
`define MIPS_CPU_REGISTER_SP_NO 5'b11101
`define MIPS_CPU_REGISTER_FP_NO 5'b11110
`define MIPS_CPU_REGISTER_RA_NO 5'b11111

`define EXTENDED_REGISTER_ADDRESS_WIDTH 6
`define MIPS_CPU_EXTENDED_REGISTER_ZERO_NO 6'b000000
`define MIPS_CPU_EXTENDED_REGISTER_HI_NO 6'b100000
`define MIPS_CPU_EXTENDED_REGISTER_LO_NO 6'b100001

`define REGISTER_MUTEX_LENGTH 3
